.TH std::ranges::shift_left,std::ranges::shift_right 3 "2024.06.10" "http://cppreference.com" "C++ Standard Libary"
.SH NAME
std::ranges::shift_left,std::ranges::shift_right \- std::ranges::shift_left,std::ranges::shift_right

.SH Synopsis
   Defined in header <algorithm>
   Call signature
   template< std::permutable I, std::sentinel_for<I> S >

   constexpr ranges::subrange<I>                                    \fB(1)\fP (since C++23)

       shift_left( I first, S last, std::iter_difference_t<I> n );
   template< ranges::forward_range R >

   requires std::permutable<ranges::iterator_t<R>>                  \fB(2)\fP (since C++23)
   constexpr ranges::borrowed_subrange_t<R>

       shift_left( R&& r, ranges::range_difference_t<R> n );
   template< std::permutable I, std::sentinel_for<I> S >

   constexpr ranges::subrange<I>                                    \fB(3)\fP (since C++23)

       shift_right( I first, S last, std::iter_difference_t<I> n );
   template< ranges::forward_range R >

   requires std::permutable<ranges::iterator_t<R>>                  \fB(4)\fP (since C++23)
   constexpr ranges::borrowed_subrange_t<R>

       shift_right( R&& r, ranges::range_difference_t<R> n );

   Shifts the elements in the range [first, last) or r by n positions. The behavior is
   undefined if [first, last) is not a valid range.

   1) Shifts the elements towards the beginning of the range:
     * If n == 0 || n >= last - first, there are no effects.
     * If n < 0, the behavior is undefined.
     * Otherwise, for every integer i in [0, last - first - n), moves the element
       originally at position first + n + i to position first + i. The moves are
       performed in increasing order of i starting from 0.
   3) Shifts the elements towards the end of the range:
     * If n == 0 || n >= last - first, there are no effects.
     * If n < 0, the behavior is undefined.
     * Otherwise, for every integer i in [0, last - first - n), moves the element
       originally at position first + i to position first + n + i. If I models
       bidirectional_iterator, then the moves are performed in decreasing order of i
       starting from last - first - n - 1.
   2,4) Same as \fB(1)\fP or \fB(3)\fP respectively, but uses r as the range, as if using
   ranges::begin(r) as first and ranges::end(r) as last.

   Elements that are in the original range but not the new range are left in a valid
   but unspecified state.

   The function-like entities described on this page are niebloids, that is:

     * Explicit template argument lists cannot be specified when calling any of them.
     * None of them are visible to argument-dependent lookup.
     * When any of them are found by normal unqualified lookup as the name to the left
       of the function-call operator, argument-dependent lookup is inhibited.

   In practice, they may be implemented as function objects, or with special compiler
   extensions.

.SH Parameters

   first - the beginning of the original range
   last  - the end of the original range
   r     - the range of elements to shift
   n     - the number of positions to shift

.SH Return value

   1,2) {first, /*NEW_LAST*/}, where NEW_LAST is the end of the resulting range and
   equivalent to:
     * first + (last - first - n), if n is less than last - first;
     * first otherwise.
   3,4) {/*NEW_FIRST*/, last}, where NEW_FIRST is the beginning of the resulting range
   and equivalent to:
     * first + n, if n is less than last - first;
     * last otherwise.

.SH Complexity

   1,2) At most ranges::distance(first, last) - n assignments.
   3,4) At most ranges::distance(first, last) - n assignment or swaps.

.SH Notes

   ranges::shift_left / ranges::shift_right has better efficiency on common
   implementations if I models bidirectional_iterator or (better)
   random_access_iterator.

   Implementations (e.g. MSVC STL) may enable vectorization when the iterator type
   models contiguous_iterator and swapping its value type calls neither non-trivial
   special member function nor ADL-found swap.

   Feature-test macro  Value    Std                        Feature
   __cpp_lib_shift    202202L (C++23) std::ranges::shift_left and
                                      std::ranges::shift_right

.SH Example


// Run this code

 #include <algorithm>
 #include <iostream>
 #include <string>
 #include <type_traits>
 #include <vector>

 struct S
 {
     int value{0};
     bool specified_state{true};

     S(int v = 0) : value{v} {}
     S(S const& rhs) = default;
     S(S&& rhs) { *this = std::move(rhs); }
     S& operator=(S const& rhs) = default;
     S& operator=(S&& rhs)
     {
         if (this != &rhs)
         {
             value = rhs.value;
             specified_state = rhs.specified_state;
             rhs.specified_state = false;
         }
         return *this;
     }
 };

 template<typename T>
 std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
 {
     for (const auto& s : v)
     {
         if constexpr (std::is_same_v<T, S>)
             s.specified_state ? os << s.value << ' ' : os << ". ";
         else if constexpr (std::is_same_v<T, std::string>)
             os << (s.empty() ? "." : s) << ' ';
         else
             os << s << ' ';
     }
     return os;
 }

 int main()
 {
     std::cout << std::left;

     std::vector<S> a{1, 2, 3, 4, 5, 6, 7};
     std::vector<int> b{1, 2, 3, 4, 5, 6, 7};
     std::vector<std::string> c{"α", "β", "γ", "δ", "ε", "ζ", "η"};

     std::cout << "vector<S> \\tvector<int> \\tvector<string>\\n";
     std::cout << a << "  " << b << "  " << c << '\\n';

     std::ranges::shift_left(a, 3);
     std::ranges::shift_left(b, 3);
     std::ranges::shift_left(c, 3);
     std::cout << a << "  " << b << "  " << c << '\\n';

     std::ranges::shift_right(a, 2);
     std::ranges::shift_right(b, 2);
     std::ranges::shift_right(c, 2);
     std::cout << a << "  " << b << "  " << c << '\\n';

     std::ranges::shift_left(a, 8); // has no effect: n >= last - first
     std::ranges::shift_left(b, 8); // ditto
     std::ranges::shift_left(c, 8); // ditto
     std::cout << a << "  " << b << "  " << c << '\\n';

 //  std::ranges::shift_left(a, -3); // UB
 }

.SH Possible output:

 vector<S>       vector<int>     vector<string>
 1 2 3 4 5 6 7   1 2 3 4 5 6 7   α β γ δ ε ζ η
 4 5 6 7 . . .   4 5 6 7 5 6 7   δ ε ζ η . . .
 . . 4 5 6 7 .   4 5 4 5 6 7 5   . . δ ε ζ η .
 . . 4 5 6 7 .   4 5 4 5 6 7 5   . . δ ε ζ η .

.SH See also

   ranges::move          moves a range of elements to a new location
   (C++20)               (niebloid)
   ranges::move_backward moves a range of elements to a new location in backwards order
   (C++20)               (niebloid)
   ranges::rotate        rotates the order of elements in a range
   (C++20)               (niebloid)
   shift_left            shifts elements in a range
   shift_right           \fI(function template)\fP
   (C++20)
